#include "qffplayer.h"
#include "ffplay.h"
#include <QDebug>
void* winID;

QFfplayer::QFfplayer(QObject *parent) : QObject(parent)
{
    /*
    *   The 'is' is a pointer global variate.
    *   When the video starts to play,
    *   it will be vaild. We need a double pointer 
    *   variate to save this pointer.
    */
    m_ppVideoState = &is;

    m_showFileName = QString("");
    winID = NULL;
    m_pauseState = 0;
    m_currentState = STATE_STOP;
    m_pPlayThd = new PlayerThread();

    /*
    *   When the play thread stop or start, we need to get it and change 
    *   the state message.
    */
    connect(m_pPlayThd, &PlayerThread::playStop, this, &QFfplayer::updateState);
    connect(m_pPlayThd, &PlayerThread::playStart, this, &QFfplayer::updateState);
}

QFfplayer::~QFfplayer()
{
    ::event_loop_flag = 0;
    if (!::is_event_loop_running && (*m_ppVideoState != NULL))
        do_exit(is);
}

/* Set the video state instance. */
void QFfplayer::setVideoState(VideoState *is)
{
    m_ppVideoState = &is;
    m_pVideoState = is;
}

/* 
*   Set the Qt window id. 
*   This window id will be used in the external module.
*   It is used the create a SDL window into the Qt window.
*/
void QFfplayer::setWinID(void *winID)
{
    ::winID = winID;
}

/* Set the display file name. */
void QFfplayer::setDisplayFile(const QString& filename)
{
    m_showFileName = filename;
}

extern "C" {
    extern Frame *frame_queue_peek_last(FrameQueue *f);
    extern int frame_queue_nb_remaining(FrameQueue *f);
    extern Frame *frame_queue_peek(FrameQueue *f);
}

/* compeleted. */
/* Get the current image which is display. */
const QImage& QFfplayer::getCurrentImage()
{
    Frame *vp;
    Frame *sp = NULL;

    vp = frame_queue_peek_last(&is->pictq);
    if (vp) {
        SwsContext* img_convert_ctx;

            img_convert_ctx = sws_getContext(is->viddec.avctx->width,
                                             is->viddec.avctx->height,
                                             is->viddec.avctx->pix_fmt,
                                             is->viddec.avctx->width,
                                             is->viddec.avctx->height,
                                             AV_PIX_FMT_RGB24,
                                             SWS_BICUBIC, NULL, NULL, NULL);

            AVFrame* frameRGB = av_frame_alloc();

            /*
            *   Change the format of the image's pixel.
            */
            avpicture_alloc((AVPicture*)frameRGB,
                            AV_PIX_FMT_RGB24,
                            is->viddec.avctx->width,
                            is->viddec.avctx->height);

            /*
            *   Scale the the image.
            */
            sws_scale(img_convert_ctx,
                      vp->frame->data,
                      vp->frame->linesize, 0,
                      is->viddec.avctx->height,
                      frameRGB->data,
                      frameRGB->linesize);

            /*
            *   Create a QImage instance via a frame message.
            */
            QImage image(frameRGB->data[0],
                         is->viddec.avctx->width,
                         is->viddec.avctx->height,
                         frameRGB->linesize[0],
                         QImage::Format_RGB888);
            m_currentImage = image;
    }
    return m_currentImage;
}

int QFfplayer::playVideo(const QString& filename)
{
    int ret;
    event_loop_flag = 1;
    if ((filename.size() == 0) || (m_currentState != STATE_STOP)) {
        qDebug() << m_currentState;
        return -1;
    }m_currentState = STATE_RUN;
    m_showFileName = filename;
    m_pPlayThd->setDisplayFile(m_showFileName);
    
    /*  
    *   We will call the play function in the another thread.
    *   Because the play function will be blocked.
    */
    m_pPlayThd->start();    
    
    return 0;
}

/* compeleted. */
int QFfplayer::stopVideo()
{
    int ret = -1;
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        event_loop_flag = 0;
        while (is_event_loop_running) {

        }
        ret = do_exit(*m_ppVideoState);
        if (ret != -1)
            m_currentState = STATE_STOP;
    }
    qDebug()<< "after stop video:" << m_currentState << is_event_loop_running;
    m_pPlayThd->terminate();
    return ret;
}

/* compeleted. */
int QFfplayer::pauseVideo()
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)/* && m_pauseState*/) {
        return m_pauseState = toggle_pause(*m_ppVideoState);
    }
    return -1;
}

/* don't use. */
int QFfplayer::resumeVideo()
{
    if (is && (m_currentState != STATE_STOP)) {
        return m_pauseState = toggle_pause(m_pVideoState);
    }
    return -1;
}

/* compeleted. */
int QFfplayer::updateVolume(int sign, double step)
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        return update_volume(*m_ppVideoState, sign, step);
    }
    return -1;
}

/* compeleted. */
int QFfplayer::muteAudio()
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        return ::toggle_mute(*m_ppVideoState);
    }
    return -1;
}

/* compeleted. */
int QFfplayer::changeShowMode()
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        return change_show_mode(*m_ppVideoState);
    }
    return -1;
}

/* comeleted. */
int QFfplayer::setSubtitleFile(const QString &filename)
{
    m_subtitileFileName = filename;
}

/*  compeleted  */
/* Update the speed of playing video. */
double QFfplayer::updateSpeed(double val, int relative)
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        if (relative) {
            set_clock_speed(&(*m_ppVideoState)->extclk, (*m_ppVideoState)->extclk.speed + val);
        } else {
            set_clock_speed(&(*m_ppVideoState)->extclk, val);
        }
        return (*m_ppVideoState)->extclk.speed;
    }
    return -1;
}

/* compeleted. */
/* Seek the playing position of the video. */
int QFfplayer::stream_seek_safe(double incr, int seek_by_bytes)
{
    if (*m_ppVideoState && (m_currentState != STATE_STOP)) {
        return ::stream_seek_safe(*m_ppVideoState, incr, seek_by_bytes);
    }
    return -1;
}


